home *** CD-ROM | disk | FTP | other *** search
/ SoundMaker 2003 (Professional Edition) / SoundMaker 2003 - Professional Edition.iso / midi tool / midioxse.exe / DATA.1 / midiecho.rex < prev    next >
OS/2 REXX Batch file  |  1999-03-27  |  4KB  |  147 lines

  1. /* REXX: Simple MIDI Echo loop */
  2. /* Parameters: Delay Repeats Decay  */
  3. /* Example: 250 10 3 */
  4. /* Designed to be used without diverting of input */
  5.  
  6. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  7. call SysLoadFuncs 
  8.  
  9. qName = MoxGetQueueName()
  10. oldq  = RxQueue( 'Set', qName )
  11.  
  12. /* MIDI-OX creates a semaphore with same name as queue */
  13. sem = SysOpenEventSem( qName )
  14.  
  15. running = (sem <> 0)    
  16.  
  17. /* Get Command line (if any).  */
  18. parse arg dly rpt dcy
  19.  
  20. delay = 250               /* 250 millisecs */
  21. if dly <> '' then
  22.    delay = dly
  23.  
  24. repeats = 8          /* 8 repeats */
  25. if rpt <> '' then
  26.    repeats = rpt
  27.  
  28. decay = 1             /* decay rate of 1 (0 = none, 10 = complete decay) */
  29. if dcy <> '' then
  30.    decay = dcy
  31.  
  32. say "Echo Delay (msecs):" delay
  33. say "Echo Repeats:" repeats
  34. say "Decay Rate:" decay
  35.  
  36. /* Use an Object REXX Queue to store note ons and offs */
  37. echoQ = .queue~new
  38. say "Initialized..."  
  39.  
  40. do while running
  41.    someInput = (Queued() <> 0) 
  42.    someEcho  = (echoQ~Items() <> 0) 
  43.  
  44.    do while someInput | someEcho 
  45.       now = MoxGetSystemTime()  
  46.       if someInput 
  47.       then do 
  48.          pull timestamp status data1 data2
  49.  
  50.          /* Sent by MIDI-OX to signify end of program */
  51.          if timestamp = 'END_DATA' 
  52.          then do
  53.             running = 0
  54.             leave
  55.          end
  56.  
  57.          if status = 144 
  58.          then do /* only notes */
  59.             later = now + delay
  60.             event = .EchoEvent~New( later, delay, repeats, decay, status, data1, data2 )
  61.             echoQ~Queue( event )
  62.          end
  63.       end
  64.  
  65.       if someEcho 
  66.       then do
  67.          /* see if the queue head has expired yet */
  68.          event = echoQ~Peek()
  69.          if event~HasExpired( now ) 
  70.          then do
  71.             /* actually remove from Queue */
  72.             event = echoQ~Pull()
  73.          
  74.             ret = MoxOutputMidi( event~status, event~note, event~velocity )
  75.             if ret <> 0 
  76.             then do
  77.                 msg = "Error code: " || ret
  78.                call RxMessageBox msg, '', 'OK', 'STOP'  
  79.             end
  80.  
  81.             /* do we have more echos to do? */
  82.             if event~Cycle() then
  83.                echoQ~Queue( event )
  84.          end
  85.       end
  86.  
  87.       someInput = (Queued() <> 0) 
  88.       someEcho  = (echoQ~Items() <> 0) 
  89.    end
  90.  
  91.    if running 
  92.    then do
  93.       /* queue is empty: you could do other processing here */       
  94.       ret = SysWaitEventSem( sem )
  95.       if ret <> 0 
  96.       then do
  97.          running = .false
  98.          call RxMessageBox "Sem Code:" || ret, "err", 'OK', 'STOP'          
  99.       end
  100.    end
  101. end
  102.  
  103. call SysDropFuncs 
  104. exit
  105.  
  106. /* ========================================================== */
  107.  
  108. ::class EchoEvent subclass Object
  109. ::method Init
  110.   expose expire delay echos decay status note velocity 
  111.   use arg expire, delay, echos, decay, status, note, velocity 
  112.  
  113.   /* initial velocity should be less */
  114.   velocity = velocity * 3 % 4
  115.   return
  116.  
  117. ::method expire attribute
  118. ::method echos attribute 
  119. ::method status attribute
  120. ::method note attribute
  121. ::method velocity attribute
  122.  
  123. ::method HasExpired
  124.   expose expire
  125.   use arg now
  126.   
  127.   if now > expire then
  128.      return 1
  129.   return 0
  130.  
  131. ::method Cycle
  132.   expose echos velocity expire delay decay
  133.  
  134.   echos = echos - 1 /* one less echoes to go */
  135.   if echos > 0 
  136.   then do
  137.      /* softer than last echo */
  138.      velocity = velocity * (10 - decay) % 10
  139.      expire = expire + delay
  140.      return 1
  141.   end
  142.  
  143.   return 0
  144.  
  145.  
  146.  
  147.